﻿//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//    Crolengi, this program (a part of program) is gameengine based on C++\Directx
//    Copyright (C) 2008 Pashinin Anton Alekseevich (Crol)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//    (INCLUDING NEGLIGENCE OR OTHERWISE) 
//    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
//    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//    Contacts: 
//    Mail: crolengi@gmail.com
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef  Static_CObject_h
#define  Static_CObject_h

#include <d3d9.h>
#include <d3dx9.h>

#include "..\\import\\CRLEngi_strings_lib\\CRLEngi_strings.h"
#include "..\\import\\param_trees_lib\\param_trees.h"
#include "object_super_class.h"

#include "include\\Managers\\Effect_Manager.h"
#include "include\\Managers\\Light_Manager.h"

#include "include\\Utils\\defines01.h"  
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///// 
/////   :: КЛАСС СТАТИЧНОГО ОБЪЕКТА ::
///// 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Static_CObject:public Object_Super{
public:
LPD3DXMESH              pMesh          ;   // собственно сетка объекта
D3DMATERIAL9*           pMeshMaterials ;   // материалы объекта
LPDIRECT3DTEXTURE9*     pMeshTextures  ;   // текстуры объекта
DWORD                   dwNumMaterials ;   // число материалов объекта
CLREngi_Console        *Console;
CLREngi_Effect_Manager *Effect_Manager;
CLREngi_Light_Manager  *Light_Manager;
CRLEngi_string           Name;

unsigned int            NUM_EFFECTS;       // Число эффектов заявленных в структурном файле

LPDIRECT3DTEXTURE9      g_pTexture_Light_Map; // lightMap 
////////// buffers
	CRLEngi_string EffectName;
	ID3DXEffect* aEff ;

	D3DXMATRIX view, proj;

	int i;
	DWORD m;
	UINT efPasses,j_pass;

public:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////    Инициализация параметров из структуры свойств
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool              InitParameters(){

		CRLEngi_string  Buffer; 

		if(ObjProperties.head_Node!=NULL){//if0
		if(ObjProperties.NUM_LOADED>0){//if1
			
            LPD3DXBUFFER pD3DXMtrlBuffer;
			pD3DXMtrlBuffer = NULL;
			int id2;
			//AlphaBlendable

			//int	id    = ObjProperties.iLookId("_ABLEND_");
			//if (id != 0) AlphaBlendable = true;
			//id=0;

			int id    = ObjProperties.iLookId("_MODEL_FILE_");
			int count = ObjProperties.iCountParams(id) + ObjProperties.iCountKnots(id);
			if ((id>0)&&(count>0)){
				bool fail = false;
				id2 = ObjProperties.TopId(id);
				LPCSTR Lfilename;
				CRLEngi_string  filename;
				filename = (ObjProperties.iLookName(id2));
				Lfilename = filename.getChars();
				
				if ( FAILED(D3DXLoadMeshFromX( Lfilename, D3DXMESH_SYSTEMMEM, 
                                   *pd3dDevice, NULL, 
                                   &pD3DXMtrlBuffer, NULL, &dwNumMaterials, 
								   &pMesh ))){
				      Buffer = "[M.F] cannot find: " ;
				      Buffer += filename.getChars();
				      Console->AddText(Buffer,true);
				      }

				
				id    = ObjProperties.iLookId("_NAME_");
				count = ObjProperties.iCountParams(id) + ObjProperties.iCountKnots(id);
				if ((id>0)&&(count>0)){
				  id2 = ObjProperties.TopId(id);
				  Name = (ObjProperties.iLookName(id2));
				}
			   

			    id    = ObjProperties.iLookId("_LIGHT_TEX_FILE");
			    count = ObjProperties.iCountParams(id) + ObjProperties.iCountKnots(id);
			    if ((id>0)&&(count>0)){
			    fail = false;
				id2 = ObjProperties.TopId(id);
				//LPCSTR Lfilename;
				//CRLEngi_string  filename;
				filename = (ObjProperties.iLookName(id2));
				Lfilename = filename.getChars();

				  if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                                          Lfilename, 
                                                          &g_pTexture_Light_Map ) ) )  {
							                              Buffer = "[T.F] cannot find: " ;
				                                          Buffer +=filename;
				                                          Console->AddText(Buffer,1);					        
					                                      }
				                              }
				 }//if






	          //// Получаем материал и его параметры отловив параметры через
              //   pD3DXMtrlBuffer
              if (pD3DXMtrlBuffer!=NULL){
                  D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
                  pMeshMaterials = new D3DMATERIAL9[dwNumMaterials];
                  pMeshTextures  = new LPDIRECT3DTEXTURE9[dwNumMaterials];
                  for( DWORD i=0; i<dwNumMaterials; i++ ){
                       // Copy the material
                       pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
                       // Set the ambient color for the material (D3DX does not do this)
                       pMeshMaterials[i].Ambient = pMeshMaterials[i].Diffuse;
                       pMeshTextures[i] = NULL;
                       if( d3dxMaterials[i].pTextureFilename != NULL && 
                           lstrlenA(d3dxMaterials[i].pTextureFilename) > 0 )  {
                              // Create the texturesaw
                              if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice,
                                                d3dxMaterials[i].pTextureFilename, 
                                                &pMeshTextures[i] ) ) )  {
				                     CRLEngi_string  texfile;
				                     texfile = "textures\\";
				                     texfile +=  d3dxMaterials[i].pTextureFilename;
				                     if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                                                              texfile.getChars(), 
                                                                             &pMeshTextures[i] ) ) ) {

                                              if( FAILED( D3DXCreateTextureFromFileA( *pd3dDevice, 
                                                                                      "textures\\_def\\def.bmp", 
                                                                                         &pMeshTextures[i] ) ) )  {
							                              Buffer = "[T.F] cannot find: " ;
				                                          Buffer += d3dxMaterials[i].pTextureFilename;
				                                          Console->AddText(Buffer,1);					        
					                                      }
				                              }
			                         }

            
                               }
				        }//for

              // Done with the material buffer
              pD3DXMtrlBuffer->Release();
			  }   

             // GOMatrixTranslateDef(&GOMatrixDef);
			  LookForNumEffects();

                




   
             D3DXMatrixTranslation(&GOMatrixDef,Position.x,Position.y,Position.z);

             D3DXMATRIX Rotate;

             D3DXMatrixIdentity(&Rotate); 
  
             D3DXMatrixRotationX( &Rotate, (D3DX_PI/180)*Rotation.x );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);
             D3DXMatrixRotationY( &Rotate, (D3DX_PI/180)*Rotation.y );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);
             D3DXMatrixRotationZ( &Rotate, (D3DX_PI/180)*Rotation.z );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);

		}//if1
		//для возможных расширений класса
        InitParameters2();

	}//if0
	else{
           Console->AddText("[!] Object File is corrupted and parameters are not loaded!",1);
		   return false;
		   }
		return true;
}//void
void update_position(){

	

             D3DXMATRIX Rotate,tr;

             D3DXMatrixIdentity(&Rotate); D3DXMatrixIdentity(&tr); D3DXMatrixIdentity(&GOMatrixDef); 
  
             D3DXMatrixRotationX( &Rotate, (D3DX_PI/180)*Rotation.x );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);
             D3DXMatrixRotationY( &Rotate, (D3DX_PI/180)*Rotation.y );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);
             D3DXMatrixRotationZ( &Rotate, (D3DX_PI/180)*Rotation.z );
             D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&Rotate);

			  D3DXMatrixTranslation(&tr,Position.x,Position.y,Position.z);

			   D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&tr);

}
void rotate(D3DXMATRIX *Rotate){
	D3DXMatrixIdentity(&GOMatrixDef); 
 D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,Rotate);

}
void update_only_position(){
	 D3DXMATRIX tr;
	 D3DXMatrixIdentity(&tr); //
     D3DXMatrixTranslation(&tr,Position.x,Position.y,Position.z);

	 D3DXMatrixMultiply(&GOMatrixDef,&GOMatrixDef,&tr);
}

virtual bool InitParameters2(){
	return true;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////    Получение числа эффектов у данного объекта,
/////    для циклов отрисовки, параметры берутся из структуры свойств
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void              LookForNumEffects(){
	int id1;

	id1 = ObjProperties.iLookId("_FX_");
	NUM_EFFECTS =  ObjProperties.iCountKnots(id1) + ObjProperties.iCountParams(id1);

}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////    Получение эффекта из менеджера эффектов
/////    по имени из структуры свойств объекта по номеру
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CRLEngi_string    LookForEffects(unsigned int num){

	    //CRLEngi_string none;
	    //none = "none";
		short id1,id2;//,id3,count;
		id1 = ObjProperties.iLookId("_FX_");
		//count =  ObjProperties.iCountKnots(id1) + ObjProperties.iCountParams(id1);
		//if (num==1){
		//	id2 = ObjProperties.TopId(id1);
		//	return ObjProperties.iLookName(id2);		
		//}else
		//if(num>1){
		if (NUM_EFFECTS>0){
			id2 = ObjProperties.TopId(id1);
			for (int i = 2;i<=NUM_EFFECTS;i++){
				id2 = ObjProperties.NextId(id2);			
			}
			return ObjProperties.iLookName(id2);

		}
		else {CRLEngi_string none;none = "none";return none;}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////    Передача параметров текстур и матриц в шейдер
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void              SetupEffect(ID3DXEffect *aEffect,D3DXMATRIX* Cview,D3DXMATRIX* Cproj){

	if (aEffect!=NULL){
	//D3DXMATRIX  matWorld;
	//D3DXMATRIX  matView;
	//D3DXMATRIX  matProj;

	D3DXMATRIX  world_view_proj;
	//D3DXMATRIX  world_view;
	//D3DXMATRIX  view_proj;

	//(*pd3dDevice)->GetTransform(D3DTS_WORLD,      &matWorld);
	//matWorld = GOMatrixDef;
	//(*pd3dDevice)->GetTransform(D3DTS_VIEW,       &matView);
	//matView = (*Cview);
	//(*pd3dDevice)->GetTransform(D3DTS_PROJECTION, &matProj);
	//matProj = (*Cproj);
	
	//view_proj       =  matView * matProj;

	//world_view_proj =  matWorld * matView * matProj;
	world_view_proj =  GOMatrixDef * (*Cview) * (*Cproj);
	//world_view      =  matWorld * matView;

	aEffect->SetMatrix(	"mat_World_View_Proj",    &world_view_proj);
	aEffect->SetMatrix(	"matWorld",               &GOMatrixDef);

	//aEffect->SetMatrix(	"World",               &matWorld);
	//aEffect->SetMatrix(	"WorldXf",             &matWorld);
	//aEffect->SetMatrix(	"View",                &matView);
    //aEffect->SetMatrix(	"ViewProjection",      &view_proj);
/*	aEffect->SetMatrix(	"Projection",          &matProj);
	aEffect->SetMatrix(	"WorldViewProjection", &world_view_proj);  
	aEffect->SetMatrix(	"WvpXf"              , &world_view_proj);  
			
	aEffect->SetMatrix(	"WorldViewProj",       &world_view_proj);
	aEffect->SetMatrix(	"WorldView",           &world_view);

	    D3DXMatrixInverse(&matView,NULL,&matView);
		
	aEffect->SetMatrix(	"ViewIXf",             &matView);	

	    D3DXMatrixInverse(   &world_view,NULL,&world_view);
	aEffect->SetMatrix(	"WorldViewInverse",    &world_view);

	    D3DXMatrixInverse(   &matWorld,NULL,&matWorld);
	    D3DXMatrixTranspose( &matWorld,&matWorld);
	aEffect->SetMatrix(	"WorldITXf",           &matWorld);


	D3DXVECTOR4 Light_Position = D3DXVECTOR4(1100,400,0,1.0f);
	D3DXVECTOR4 Light_Color = D3DXVECTOR4(0.5f, 0.5f, 0.5f, 1.0f);

	aEffect->SetVector( "LightPos", &Light_Position);
	aEffect->SetVector( "LightColor", &Light_Color);*/


		//aEffect->SetFloat(  "LightFalloff", 1000.0f );
		//aEffect->SetFloat(  "LightSpecular", 8.5f );
		//aEffect->SetFloat(  "LightSpecular_Itens", 0.59f );
		//aEffect->SetFloat(  "LightAmbient", 0.005f );
		//aEffect->SetFloat(  "Attenuation", 0.8f );
		//aEffect->SetTechnique( "ald_Phong" );

	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////    Отрисовка
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void              Render(unsigned int LightId,bool Lfirst){

	if (Lfirst)
	Positioning();	
/*
	if (NUM_EFFECTS>0){
	for (i = 1;i<=NUM_EFFECTS;i++){

		EffectName = LookForEffects(i);
		
		aEff = Effect_Manager->GetEffect(EffectName,&view,&proj);
		
		SetupEffect(aEff,&view,&proj);
		

		if (aEff!=NULL)
		{
			Light_Manager->SetupEffect(aEff,LightId);

			
			if (Lfirst)
			    aEff->SetTechnique( "ald_Phong" );
			else
				aEff->SetTechnique( "ald_Phong_alpha" );

		    //UINT efPasses;
		    aEff->Begin(&efPasses,NULL);
		    for( j_pass = 0;j_pass<efPasses;j_pass++)
		    {
			    aEff->BeginPass(j_pass);

			  	  for( DWORD m=0; m<dwNumMaterials; m++ ){
				      (*pd3dDevice)->SetMaterial( &pMeshMaterials[m] );
					  (*pd3dDevice)->SetTexture( 0, pMeshTextures[m] );
					  pMesh->DrawSubset( m );
				  }//for

			    aEff->EndPass();
	        }//for
	        aEff->End();
		}//if
		else{
			for(  m=0; m<dwNumMaterials; m++ ){
				    (*pd3dDevice)->SetMaterial( &pMeshMaterials[m] );
					(*pd3dDevice)->SetTexture( 0, pMeshTextures[m] );
					pMesh->DrawSubset( m );
				}//for		
		}
	}}//for//if
	else
	{
		for(  m=0; m<dwNumMaterials; m++ ){
				    (*pd3dDevice)->SetMaterial( &pMeshMaterials[m] );
					(*pd3dDevice)->SetTexture( 0, pMeshTextures[m] );
					pMesh->DrawSubset( m );
				}//for
	}
*/
	if (g_pTexture_Light_Map!=NULL){

		bool g_bModulate = false;
	//
	// STAGE 0
	//

	(*pd3dDevice)->SetSamplerState( 0, D3DSAMP_MINFILTER, 3 );
	(*pd3dDevice)->SetSamplerState( 0, D3DSAMP_MAGFILTER, 3  );

	(*pd3dDevice)->SetSamplerState( 1, D3DSAMP_MINFILTER, 6 );
	(*pd3dDevice)->SetSamplerState( 1, D3DSAMP_MAGFILTER, 6 ); 

    (*pd3dDevice)->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX,0 );
	(*pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLOROP,  4 ); // Modulate...
	(*pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );   // the texture for this stage with...
	(*pd3dDevice)->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );   // the diffuse color of the geometry.




    (*pd3dDevice)->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 2);

	if( g_bModulate == true )
		(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_MODULATE ); // Modulate...
	else
		(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_COLOROP, 4 ); // or Add...

	(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE ); // the texture for this stage with...
	(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT ); // the current argument passed down from stage 0

//(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP); 
//(*pd3dDevice)->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);

	//g_pd3dDevice->SetTexture( 0, g_pTexture_0 );
	
	for( DWORD m=0; m<dwNumMaterials; m++ ){
				    (*pd3dDevice)->SetMaterial( &pMeshMaterials[m] );
					(*pd3dDevice)->SetTexture( 0, pMeshTextures[m] );
					(*pd3dDevice)->SetTexture( 1, g_pTexture_Light_Map );
					pMesh->DrawSubset( m );
				}//for
	(*pd3dDevice)->SetTexture( 0,NULL);
	(*pd3dDevice)->SetTexture( 1, NULL );
	
	}
	else
	for( DWORD m=0; m<dwNumMaterials; m++ ){
				    (*pd3dDevice)->SetMaterial( &pMeshMaterials[m] );
					(*pd3dDevice)->SetTexture( 0, pMeshTextures[m] );
					pMesh->DrawSubset( m );
				}//for
		
	}//void
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                     КОНСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public:
Static_CObject(D3DXMATRIXA16*            GMatrix,
		       char*                     FProperties,
			   LPDIRECT3DDEVICE9        *Device,
			   CLREngi_Effect_Manager   *Eff_Manager,
			   CLREngi_Light_Manager    *L_Manager,
		       CLREngi_Console           *Cnsl){ 

		Console=Cnsl;

		GOMatrixDef = *GMatrix;             // получаем мировую матрицу проекции
	    D3DXMatrixIdentity(&GOMatrix);     // обрабатываем созданную матрицу

		CRLEngi_string file;
		file = FProperties;
		ObjProperties.iLoadFromFile(file); //загрузка параметров

		dwNumMaterials= 0 ;
		Position = D3DXVECTOR3(0.0f,0.0f,0.0f);		

		Effect_Manager = Eff_Manager;

		Light_Manager = L_Manager;

		pd3dDevice = Device;

		aEff=NULL;

		g_pTexture_Light_Map = NULL;

	};
Static_CObject(){};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                       ДЕСТРУКТОР
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ~Static_CObject(){
		//int i =1;


SAFE_RELEASE_P(pMesh);
    if( pMeshTextures )
    {
        for( DWORD i = 0; i < dwNumMaterials; i++ )
        {
            if( pMeshTextures[i] )
                pMeshTextures[i]->Release();
        }
        delete[] pMeshTextures;
    }
 if( pMeshMaterials != NULL ) 
        delete[] pMeshMaterials;


	};

};

#endif 